/* Gyroe 1.0.0 */
/* emit.c : Generate code to execute internal and user
   declared routines and ops. */

#include "euphoria.h"
#include "main-.h"
#include "sym_fields.h"

int _14Push(int x)
{
    Append(&_14cg_stack, _14cg_stack, x);
}

int _14Top()
{
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    return *(ptr->base + ptr->length); // cg_stack[$]
}

int _14Pop()
{
    int a, end;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    a = *(ptr->base + ptr->length); // cg_stack[$]

    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[a][S_MODE] == M_TEMP
    if (*(Base + S_MODE) == 3)
        // SymTab[a][S_SCOPE] = FREE
        *(Base + S_SCOPE) = 0;

    return a;
}

int _14TempKeep(int a)
{
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[a][S_MODE] == M_TEMP
    if (Base[S_MODE] == 3)
        // SymTab[a][S_SCOPE] = IN_USE
        Base[S_SCOPE] = 1;
}

int _14TempFree(int a)
{
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[a][S_MODE] == M_TEMP
    if (Base[S_MODE] == 3)
        // SymTab[a][S_SCOPE] = FREE
        Base[S_SCOPE] = 0;
}

int _14TempInteger(int a)
{
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[a][S_MODE] == M_TEMP
    if (Base[S_MODE] == 3)
        // SymTab[a][S_USAGE] = T_INTEGER
        Base[S_USAGE] = 1;
}

int _14LexName(int t)
/* Return a string for t. For outputting error messages of
   Expected 'x' not 'y'. */
{
    int i = 0, j = 0;
    object_ptr Base;
    s1_ptr ptr;

    /* 59 is the length of token_name */
    while (i <= 59) {
        i++;
        ptr = SEQ_PTR(_14token_name);
        Base = ptr->base + i;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base + 1; // token_name[i][LEX_NUMBER]
        if (t == *Base) {
            j = 1;
            break;
        }
    }

    /* Did we catch a symbol? */
    if (j == 0) {
        /* No. Substitute '...' */
        return NewString("...");
    }

    ptr = SEQ_PTR(_14token_name);
    Base = ptr->base + i;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base + 2; // token_name[i][LEX_NAME]
    return *Base;
}

int _14InitEmit()
{
    //     cg_stack = {}
    RefDS(_39);
    DeRefi(_14cg_stack);
    _14cg_stack = _39;
}

int _14IsInteger(int sym)
{
    int mode, pt, t;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + sym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    mode = Base[S_MODE]; // SymTab[sym][S_MODE]

    // mode == M_NORMAL
    if (mode == 1) {
        t = Base[S_VTYPE]; // SymTab[sym][S_VTYPE]

        if (t == _10integer_type)
            return 1; // TRUE

        if (t) {
            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + t;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base;

            pt = Base[S_NEXT]; // SymTab[t][S_NEXT]

            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + pt;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base; // SymTab[pt][S_VTYPE]
            // if pt and SymTab[pt][S_VTYPE] = integer_type then
            if (pt && Base[S_VTYPE] == _10integer_type)
                return 1; // TRUE /* usertype (integer x) */
        }
    }

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + sym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // mode == M_CONSTANT
    if (mode == 2) {
        // if integer(SymTab[sym][S_OBJ]) -- bug fixed: can't allow PLUS1_I op
        if (IS_ATOM_INT(Base[S_OBJ]))
            return 1; // TRUE
    }

    // mode == M_TEMP
    if (mode == 3) {
        // SymTab[sym][S_USAGE] == T_INTEGER
        if (Base[S_USAGE] == 1)
            return 1; // TRUE
    }

    return 0; // FALSE
}

int _14emit(int val)
{
    Append(&_4Code, _4Code, val);
}

int _14emit_opnd(int opnd)
{
    _14Push(opnd);
    _14previous_op = -1; /* N.B */
}

int _14emit_addr(int x)
{
    Append(&_4Code, _4Code, x);
}

int _14backpatch(int index, int val)
{
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4Code);
    Base = ptr->base;
    Base[index] = val;
}

int _14cont11ii(int op, int ii)
{
    int c, source, t;
    s1_ptr ptr;

    _14emit(op);
    source = _14Pop();
    _14emit(source);
    _14assignable = 1; // TRUE

    ptr = SEQ_PTR(_14op_result);
    t = *(ptr->base + op); // op_result[op]

    c = _10NewTempSym();

    if (t == 1 || ii && _14IsInteger(source))
        _14TempInteger(c);

    _14Push(c);
    _14emit(c);
}

int _14cont21d(int op, int a, int b, int ii)
{
    int c, t;
    s1_ptr ptr;

    _14assignable = 1; // TRUE

    ptr = SEQ_PTR(_14op_result);
    t = *(ptr->base + op); // op_result[op]

    c = _10NewTempSym();

    if (t == 1 || ii && _14IsInteger(a) && _14IsInteger(b))
        _14TempInteger(c);

    _14Push(c);
    _14emit(c);
}

int _14cont21ii(int op, int ii)
{
    int a, b;

    _14emit(op);
    b = _14Pop();
    a = _14Pop();
    _14emit(a);
    _14emit(b);

    _14cont21d(op, a, b, ii);
}

int _14good_string(int elements)
{
    int e, i, len;
    int obj, mode;
    object_ptr Base;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(elements);
    len = ptr0->length + 1;

    for(i = 1;i < len;i++) {
        e = *(ptr0->base + i);

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + e;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        obj = *(Base + 1); // SymTab[e][S_OBJ]
        mode = *(Base + 3); // SymTab[e][S_MODE]

        // mode != M_CONSTANT or not integer(obj)
        if (mode != 2 || !IS_ATOM_INT(obj))
            return -1;
    }

    /* If we're down here, all of the [e][S_OBJ] parts must have been okay.
       Create a blank S1, then fill in reverse order with the S_OBJ parts. */

    int ptr2_;
    object_ptr Base2;

    ptr2_ = NewS1(len-1);
    Base2 = ((s1_ptr)ptr2_)->base;

    for (i = 1;i < len;i++) {
        e = *(ptr0->base + len - i);
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + e;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
        Base2[i] = Base[S_OBJ]; // elements[e][S_OBJ]
    }

    return MAKE_SEQ(ptr2_);
}

int emit_assign()
{
    int op = 18;
    int source, target;
    object_ptr Base;
    s1_ptr ptr;

    source = _14Pop();
    target = _14Pop();

    if (_14assignable) {
        /* Drop previous code target... */
        ptr = SEQ_PTR(_4Code);
        rhs_slice_target = (object_ptr)&_4Code;
        RHS_Slice((s1_ptr)_4Code, 1, ptr->length - 1);

        /* ...but keep the previous op. */
        op = _14previous_op;

        if (_14IsInteger(target)) {

            ptr = SEQ_PTR(_4Code);
            Base = ptr->base + ptr->length;

            switch (_14previous_op) {
                case 25: // RHS_SUBS
                    op = 114; // RHS_SUBS_I

                    _14backpatch(ptr->length - 2, 114); // RHS_SUBS_I
                    break;
                case 93: // PLUS1
                    op = 117; // PLUS1_I

                    _14backpatch(ptr->length - 2, 117); // PLUS1_I
                    break;
                case 11: // PLUS
                case 10: // MINUS
                    if (_14IsInteger(*Base) && _14IsInteger(*(Base - 1))) {
                        if (_14previous_op == 11) // PLUS
                            op = 115; // PLUS_I
                        else
                            op = 116; // MINUS_I

                        _14backpatch(ptr->length - 2, op);
                    }
                    break;
                default:
                    if (_14IsInteger(source))
                        op = 113; // ASSIGN_I /* Fake to avoid subsequent check */
                    break;
            }
        }
    }
    else {
        /* Make an extra Base for target. */
        object_ptr Base2;

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + source; // SymTab[source]
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        ptr = SEQ_PTR(_4SymTab);
        Base2 = ptr->base + target; // SymTab[target]
        ptr = SEQ_PTR(*Base2);
        Base2 = ptr->base;

        // SymTab[source][S_MODE] == M_CONSTANT && SymTab[target][S_MODE] == M_CONSTANT
        if (Base[S_MODE] == 2 && Base2[S_MODE] == 2)
            // SymTab[target][S_OBJ] = SymTab[source][S_OBJ]
            Base2[S_OBJ] = Base[S_OBJ];
        _14emit(op);
        _14emit(source);
    }

    _14assignable = 0; // FALSE
    _14emit(target);
    _14previous_op = op;
    return op;
}

void emit_assign_op_slice(int op)
{
    int a, b, c, d;
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    a = *point; /* rhs value not used */
    b = *(point - 1); /* 2nd subs */
    c = *(point - 2); /* 1st subs */
    d = *(point - 3); /* sequence */

    _14emit(d);
    _14emit(c);
    _14emit(b);

    c = _10NewTempSym();
    *point = c;

    _14emit(c); /* place to store result */
    _14Push(a);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_assign_slice(int op)
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    _14emit(*(point - 3)); /* sequence */
    _14emit(*(point - 2)); /* 1st subs */
    _14emit(*(point - 1)); /* 2nd subs */
    _14emit(*point); /* rhs value */

    end = ptr->length - 4;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

int emit_assign_subs()
{
    int a, b, c, end, op = 16;
    int _2456 = 0, _2481 = 0, _2441, _2667 = 0;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;

    a = *point0; /* rhs value */
    b = *(point0 - 1); /* subscript */
    c = *(point0 - 2); /* sequence */

    end = ptr0->length - 3;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    if (_14previous_op != 95) { // LHS_SUBS
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + c;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        _2441 = Base[S_MODE]; // SymTab[c][S_MODE]
        _2481 = Base[S_VTYPE]; // SymTab[c][S_VTYPE]

        if (_2441 != 1) { // M_NORMAL
            if (_2481 != _10sequence_type) {
                object_ptr vtype;
                *vtype = _2481;
                ptr = SEQ_PTR(_4SymTab);
                vtype = ptr->base + *vtype;
                ptr = SEQ_PTR(*vtype);
                vtype = ptr->base + 2; // SymTab[SymTab[c][S_VTYPE]][S_NEXT]
                ptr = SEQ_PTR(_4SymTab);
                vtype = ptr->base + *vtype;
                ptr = SEQ_PTR(*vtype);
                vtype = ptr->base + 14; // SymTab[SymTab[c][S_VTYPE]][S_NEXT]][S_VTYPE]
                _2667 = (*vtype != _10sequence_type);
                _2481 = (_2667 != 0);
            }
            _2441 = (_2481 != 0);
        }

       if (_2441) {
           op = 84; // ASSIGN_SUBS_CHECK
       }
    }
    else {
        if (_14IsInteger(b))
            op = 118; // ASSIGN_SUBS_I
    }

    _14emit(op);
    _14emit(c); /* sequence */
    _14emit(b); /* subscript */
    _14emit(a); /* rhs value */
    _14assignable = 0; // FALSE

    _14previous_op = op;
    return op;
}

void emit_assign_subs2()
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(16); // ASSIGN_SUBS
    _14emit(*(point - 2)); /* sequence */
    _14emit(*(point - 1)); /* subscript */
    _14emit(*point); /* rhs value */

    end = ptr->length - 3;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = 150;
}

void emit_atom_check()
{
    int c;
    object_ptr Base;
    s1_ptr ptr;

    _14assignable = 0; // FALSE

    if (_14previous_op == 18) { // ASSIGN
        ptr = SEQ_PTR(_4Code);
        c = *(ptr->base + ptr->length - 1); // Code[$-1]

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + c;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // if (SymTab[c][S_MODE] != M_CONSTANT || SymTab[c][S_OBJ] == 0
        if (Base[S_MODE] != 2 || IS_ATOM(Base[S_OBJ]) == 0) {
            _14emit(101); // ATOM_CHECK
            _14emit(_14op_info1);
        }
    }
    else {
        ptr = SEQ_PTR(_14op_result);
        Base = ptr->base + _14previous_op; // op_result[previous_op]

        // previous_op == -1 || op_result[previous_op] != T_INTEGER && op_result[previous_op] != T_ATOM
        if (_14previous_op == -1 || *Base != 1 && *Base != 4) {
            _14emit(101); // ATOM_CHECK
            _14emit(_14op_info1);
        }
    }
    _14previous_op = 101; // ATOM_CHECK
}

void emit_c_func()
/* Special case : Do cont21ii and cont21d here since C_FUNC needs an extra emit.
   This saves everything else which calls cont21ii or cont21d from an extra if. */
{
    int a, b, c, end, ii = 0;
    int op = 135, t;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(135);
    _14emit(*(point - 1));
    _14emit(*point);

    ptr = SEQ_PTR(_14op_result);
    t = *(ptr->base + 135); // op_result[op]

    _14emit(_4CurrentSub);
    c = _10NewTempSym();

    if (t == 1 || ii && _14IsInteger(a) && _14IsInteger(b))
        _14TempInteger(c);

    *(point - 1) = c;

    ptr = SEQ_PTR(_14cg_stack);

    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14emit(c);
    _14assignable = 1; // TRUE
}

void emit_call_func()
{
    int a, end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(139); // CALL_FUNC
    _14emit(*(point - 1));
    _14emit(*point);

    a = _10NewTempSym();
    *(point - 1) = a;
    _14emit(a);

    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 1; // TRUE
}

void emit_concat_n()
{
    int c, end, i, n;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    n = _14op_info1; /* number of items to concatenate */
    _14emit(159); // CONCAT_N
    _14emit(n);

    for (i = 0;i < n;i++) {
        _14emit(*(point - i)); /* reverse order */
    }

    end = ptr->length - n;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    c = _10NewTempSym();
    _14emit(c);
    _14Push(c);
    _14assignable = 1; // TRUE
    _14previous_op = 159;
}

int emit_divide()
{
    int a, end;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;
    a = *point0;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // if SymTab[a][S_MODE] == M_CONSTANT && SymTab[a][S_OBJ] == 2
    if (Base[S_MODE] == 2 && Base[S_OBJ] == 2) {
        _14emit(98); // DIV2
        _14emit(*(point0 - 1));
        _14emit(0);
        end = ptr0->length - 2;
        rhs_slice_target = (object_ptr)&_14cg_stack;
        RHS_Slice((s1_ptr)_14cg_stack, 1, end);
        _14cont21d(98, 0, a, 0); /* could have fractional result */
        _14previous_op = 98;
        return 98; // DIV2
    }

    _14cont21ii(14, 0); // DIV
    _14previous_op = 14;
    return 14; // DIV
}

void emit_dollar()
{
    int a, len;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14current_sequence);
    len = ptr->length;

    if (_14lhs_ptr && len == 1) {
        _14emit(162); // PLENGTH
    }
    else {
        _14emit(42); // LENGTH
    }

    Base = ptr->base + len;
    _14emit(*Base);

    a = _10NewTempSym();
    _14TempInteger(a);

    _14Push(a);
    _14emit(a);

    _14previous_op = -22; // DOLLAR
    _14assignable = 0; // FALSE
}

void emit_endfor(int op)
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op); /* will be patched at runtime */
    _14emit(_14op_info2); /* address at the top of the loop */
    _14emit(*(point - 1)); /* not sure what this is for */
    _14emit(_14op_info1); /* loop var */
    _14emit(*point); /* increment - not always used */

    end = ptr->length - 2;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

int emit_floor()
{
    s1_ptr ptr;

    ptr = SEQ_PTR(_4Code);

    if (_14previous_op == 14) { // DIVIDE
        _14backpatch(ptr->length - 3, 63);
        _14assignable = 1; // TRUE
        return 63; // FLOOR_DIV
    }
    else {
        if (_14previous_op == 98) { // DIV2
            object_ptr Base;

            _14backpatch(ptr->length - 3, 66);
            _14assignable = 1; // TRUE
            Base = ptr->base + ptr->length; // Code[$]
            if (_14IsInteger(*(Base - 2)))
                _14TempInteger(_14Top()); /* mark the temp as integer type */
            return 66; // FLOOR_DIV2
        }
        else {
            _14cont11ii(83, 1);
            return 83; // FLOOR
        }
    }
}

int emit_for()
{
    int a, b, c, mode, op, scope;
    object_ptr Base;
    s1_ptr ptr;

    c = _14Pop(); /* increment */
    _14TempKeep(c);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + c;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    mode = Base[S_MODE];

    // mode == M_NORMAL
    if (mode == 1) {
        scope = *(Base + 4);
        // scope != LOOP_VAR && scope != GLOOP_VAR
        if (scope != 2 && scope != 4) {
            _14emit(18); // ASSIGN
            _14emit(c);
            c = _10NewTempSym();
            _14emit(c);
        }
    }

    b = _14Pop(); /* limit */
    _14TempKeep(b);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + b;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    mode = Base[S_MODE];

    // mode == M_NORMAL
    if (mode == 1) {
        scope = Base[S_SCOPE]; // SymTab[b][S_SCOPE]
        // scope != LOOP_VAR && scope != GLOOP_VAR
        if (scope != 2 && scope != 4) {
            _14emit(18); // ASSIGN
            _14emit(b);
            b = _10NewTempSym();
            _14emit(b);
        }
    }

    a = _14Pop(); /* initial value */

    if (_14IsInteger(a) && _14IsInteger(b) && _14IsInteger(c)) {
        // SymTab[op_info1][S_VTYPE] = integer_type
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + _14op_info1;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
        Base[S_VTYPE] = _10integer_type;
        op = 125; // FOR_I
    }
    else {
        op = 21; // FOR
    }

    _14emit(op);
    _14emit(c);
    _14emit(b);
    _14emit(a);
    _14emit(_4CurrentSub); /* in case recursion check is needed */
    _14Push(b);
    _14Push(c);
    _14assignable = 0; // FALSE
    _14previous_op = op;
    return op;
}

void emit_get_key()
/* Do code for emit_m4 so we don't have to do an if for GET_KEY */
{
    int a;

    _14emit(79); // GET_KEY
    a = _10NewTempSym();
    _14TempInteger(a); /* For GET_KEY */
    _14Push(a);
    _14emit(a);

    _14assignable = 1; // TRUE
}

int emit_ifwhile(int op)
{
    int a, end;
    object_ptr Base;
    s1_ptr ptr;

    /* Not worth it to undo the pop. Too many backpatches, no pushes. */
    a = _14Pop();

    _14assignable = 0; // FALSE

    // 	if previous_op >= LESS and previous_op <= NOT then
    if (_14previous_op >= 1 && _14previous_op <= 7) {
        ptr = SEQ_PTR(_4Code);
        end = ptr->length - 1;
        rhs_slice_target = (object_ptr)&_4Code;
        RHS_Slice((s1_ptr)_4Code, 1, end);

        ptr = SEQ_PTR(_4Code);

        // if previous_op = NOT then
        if (_14previous_op == 7) {
            op = 108; // NOT_IFW
            _14backpatch(ptr->length - 1, 108);
        }
        else {
            Base = ptr->base + ptr->length; // Code[$]

            // IsInteger(Code[$]) && IsInteger(Code[$-1])
            if (_14IsInteger(*Base) && _14IsInteger(*(Base - 1)))
                op = _14previous_op + 119 - 1; // previous_op + LESS_IFW_I - LESS
            else
                op = _14previous_op + 102 - 1; // previous_op + LESS_IFW - LESS

            _14backpatch(ptr->length - 2, op);
        }
    }
    else {
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + a;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        int mode, obj;
        mode = Base[S_MODE];
        obj = Base[S_OBJ];

        // op == WHILE && mode == M_CONSTANT && integer(obj) && obj != 0
        if (op == 47 && mode == 2 && IS_ATOM_INT(obj) && obj != 0)
            _14optimized_while = 1; /* while TRUE ... emit nothing */
        else {
            _14emit(op);
            _14emit(a);
        }
    }
    return op;
}

void emit_lhs_subs(int op)
{
    int a, end, lhs_var;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    a = *point; /* subs */
    lhs_var = *(point - 1); /* sequence */

    _14emit(op);
    _14emit(lhs_var);
    _14emit(a);

    if (op == 95) { // LHS_SUBS
        _14TempKeep(lhs_var); /* should be lhs_target_temp */
        _14emit(_14lhs_target_temp);
        _14emit(0); /* place holder */
    }
    else {
        _14lhs_target_temp = _10NewTempSym(); /* same temp for all subscripts */
        _14emit(_14lhs_target_temp); /* target temp holds pointer to sequence */
        _14lhs_subs1_copy_temp = _10NewTempSym(); /* place to copy */
        _14emit(_14lhs_subs1_copy_temp);
    }

    *(point - 1) = _14lhs_target_temp;

    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    Append(&_14current_sequence, _14current_sequence, _14lhs_target_temp);

    _14assignable = 0; // FALSE /* need to update current_sequence like in RHS_SUBS */
    _14previous_op = op;
}

void emit_integer_check()
{
    int a;
    object_ptr Base;
    s1_ptr ptr;

    _14assignable = 0; // FALSE

    if (_14previous_op == 18) { // ASSIGN
        ptr = SEQ_PTR(_4Code);
        a = *(ptr->base + ptr->length - 1); // Code[$-1]

        if (!_14IsInteger(a)) {
            _14emit(96); // INTEGER_CHECK
            _14emit(_14op_info1);
        }
    }
    else {
        ptr = SEQ_PTR(_14op_result);
        Base = ptr->base + _14previous_op; // op_result[previous_op]

        // previous_op == -1 || op_result[previous_op] != T_INTEGER
        if (_14previous_op == -1 || *Base != 1) {
            _14emit(96); // INTEGER_CHECK
            _14emit(_14op_info1);
        }
    }
    _14previous_op = 96; // INTEGER_CHECK
}

/* The emit_m* ops handle a variety of operations with the same basic structure. */

int emit_m1(int op)
{
    _14emit(op);
    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_m2(int op)
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    _14emit(*(point - 1));
    _14emit(*point);

    end = ptr->length - 2;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_c_proc()
{
    emit_m2(134); // C_PROC
    _14emit(_4CurrentSub);
}

void emit_m3(int op)
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    _14emit(*(point - 2));
    _14emit(*(point - 1));
    _14emit(*point);

    end = ptr->length - 3;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14previous_op = op;
    _14assignable = 0; // FALSE
}

void emit_m4(int op)
{
    int a;

    _14emit(op);
    a = _10NewTempSym();
    _14Push(a);
    _14emit(a);

    _14assignable = 1; // TRUE
}

void emit_m5(int op)
{
    _14emit(op);
    _14emit(_14Pop());
    _14assignable = 0; // FALSE
}

void emit_multiply()
{
    int a, b, end;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;

    a = *point0;
    b = *(point0 - 1);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[a][S_MODE] == M_CONSTANT && SymTab[a][S_OBJ] == 2
    if (Base[S_MODE] == 2 && Base[S_OBJ] == 2) {
        end = ptr0->length - 2;
        rhs_slice_target = (object_ptr)&_14cg_stack;
        RHS_Slice((s1_ptr)_14cg_stack, 1, end);
        _14emit(11);
        _14emit(b);
        _14emit(b);
        _14cont21d(11, a, b, 0);
    }
    else {
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + b;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // SymTab[b][S_MODE] == M_CONSTANT && SymTab[b][S_OBJ] == 2
        if (Base[S_MODE] == 2 && Base[S_OBJ] == 2) {
            end = ptr0->length - 2;
            rhs_slice_target = (object_ptr)&_14cg_stack;
            RHS_Slice((s1_ptr)_14cg_stack, 1, end);
            _14emit(11);
            _14emit(a);
            _14emit(a);
            _14cont21d(11, a, b, 0);
        }
        else {
            _14cont21ii(13, 0); // FALSE
        }
    }
    _14previous_op = 13; // MULTIPLY
}

void emit_opsubs(int op)
{
    int a, b, c, d, end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    a = *point; /* rhs value */
    b = *(point - 1); /* subscript */
    c = *(point - 2); /* lhs sequence */

    _14emit(op);
    _14emit(c);
    _14emit(b);
    d = _10NewTempSym(); /* place to store result */
    _14emit(d);

    *point = d;

    _14Push(a);
    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_platform()
{
    int a;

    if (_4ELINUX)
        a = 3;
    if (_4EWINDOWS)
        a = 2;
    if (_4EDOS)
        a = 1;

    _14Push(_10NewIntSym(a));
    _14assignable = 0; // FALSE
}

int emit_plus()
{
    int a, b, end;
    object_ptr Base, point;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point = ptr0->base + ptr0->length;

    a = *point;
    b = *(point - 1);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[b][S_MODE] == M_CONSTANT && SymTab[b][S_OBJ] == 1
    if (Base[S_MODE] == 2 && Base[S_OBJ] == 1) {
        end = SEQ_PTR(_14cg_stack)->length - 2;
        rhs_slice_target = (object_ptr)&_14cg_stack;
        RHS_Slice((s1_ptr)_14cg_stack, 1, end);
        _14emit(93); // PLUS1
        _14emit(b);
        _14emit(0);
        _14cont21d(93, a, b, 0);
        _14previous_op = 93; // PLUS1
        return 93; // PLUS1
    }
    else {
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + b;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
        // SymTab[a][S_MODE] == M_CONSTANT && SymTab[a][S_OBJ] == 1
        if (Base[S_MODE] == 2 && Base[S_OBJ] == 1) {
            end = SEQ_PTR(_14cg_stack)->length - 2;
            rhs_slice_target = (object_ptr)&_14cg_stack;
            RHS_Slice((s1_ptr)_14cg_stack, 1, end);
            _14emit(93); // PLUS1
            _14emit(a);
            _14emit(0);
            _14cont21d(93, a, b, 0);
            _14previous_op = 93; // PLUS1
            return 93; // PLUS1
        }
        else {
            _14cont21ii(11, 0);
            _14previous_op = 11; // PLUS
            return 11; // PLUS
        }
    }
}

int emit_power()
{
    int a, b, end;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;

    a = *point0;
    b = *(point0 - 1);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // if SymTab[b][S_MODE] == M_CONSTANT && SymTab[b][S_OBJ] == 2
    if (Base[S_MODE] == 2 && Base[S_OBJ] == 2) {
        end = ptr0->length - 2;
        rhs_slice_target = (object_ptr)&_14cg_stack;
        RHS_Slice((s1_ptr)_14cg_stack, 1, end);
        _14emit(13); // MULTIPLY
        _14emit(b);
        _14emit(b);
        _14cont21d(13, a, b, 0);
        return 13; // MULTIPLY
    }

    _14cont21ii(72, 0);
    return 72; // POWER
}

void emit_proc()
{
    int a, i, n, subsym;
    int lmax, lmin;

    object_ptr Base, pos;
    s1_ptr ptr, ptr0;

    _14assignable = 0; // FALSE /* assume for now */
    subsym = _14op_info1;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + subsym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    n = Base[S_NUM_ARGS]; // SymTab[subsym][S_NUM_ARGS]

    ptr0 = SEQ_PTR(_14cg_stack);

    /* Set start and end points for the loop */
    lmin = ptr0->length - n + 1;
    lmax = ptr0->length + 1;

    if (subsym == _4CurrentSub) {
        object_ptr Base00;
        s1_ptr ptr00;
        int scope, varnum;
        for (i = lmin;i < lmax;i++) {
            pos = ptr0->base + i;
            ptr00 = SEQ_PTR(_4SymTab);
            Base00 = ptr00->base + *pos;
            ptr00 = SEQ_PTR(*Base00); // SymTab[cg_stack[i]]
            Base00 = ptr00->base;
            scope = Base00[S_SCOPE]; // SymTab[cg_stack[i]][S_SCOPE]
            varnum = Base00[S_VARNUM]; // SymTab[cg_stack[i]][S_VARNUM]
            // scope == SC_PRIVATE && varnum < i
            if (scope == 3 && varnum < i) {
                _14emit(18); // ASSIGN
                _14emit(*pos);
                *pos = _10NewTempSym();
                _14emit(*pos);
            }
        }
    }

    _14emit(27); // PROC
    _14emit(subsym);

    pos = ptr0->base + lmin; /* Pointer to first spot in the loop. */

    for (i = lmin;i < lmax;i++) {
        _14emit(*pos);
        _14TempFree(*pos);

        pos++; /* Move the pointer to the next spot. */
    }

    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, lmin - 1);

    // SymTab[subsym][S_TOKEN] != PROC
    if (Base[S_TOKEN] != 27) {
        _14assignable = 1; // TRUE
        a = _10NewTempSym(); /* temp to place the final result in */
        _14Push(a);
        _14emit(a);
    }
    _14previous_op = 27; // PROC
}

void emit_returnf()
{
    _14emit(28); // RETURNF

    _14emit(_4CurrentSub);
    _14emit(_14Pop());

    _14assignable = 0; // FALSE
    _14previous_op = 28; // RETURNF
}

void emit_returnp()
{
    _14emit(29); // RETURNP
    _14emit(_4CurrentSub);
    _14assignable = 0; // FALSE
    _14previous_op = 29; // RETURNP
}

void emit_rhs_slice()
{
    int b, c, end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(46); // RHS_SLICE

    _14emit(*(point - 2));
    _14emit(*(point - 1));
    _14emit(*point);

    c = _10NewTempSym();

    *(point - 2) = c;

    /* Slice 2, not 3. */
    end = ptr->length - 2;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14emit(c);

    _14previous_op = 46; // RHS_SLICE
    _14assignable = 1; // TRUE
}

int emit_rhs_subs()
{
    int a, b, end, mode, op = 25, target;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;

    a = *point0; /* subscript */
    b = *(point0 - 1); /* sequence */

    target = _10NewTempSym();

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + b;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    mode = Base[S_MODE]; // SymTab[c][S_MODE]
    // mode == M_NORMAL
    if (mode == 1) {
        object_ptr vtype;
        vtype = Base + S_VTYPE; // SymTab[c][S_VTYPE]
        if (*vtype != _10sequence_type) {
            ptr = SEQ_PTR(_4SymTab);
            vtype = ptr->base + *vtype;
            ptr = SEQ_PTR(*vtype);
            vtype = ptr->base + S_NEXT; // SymTab[SymTab[c][S_VTYPE]][S_NEXT]
            ptr = SEQ_PTR(_4SymTab);
            vtype = ptr->base + *vtype;
            ptr = SEQ_PTR(*vtype);
            vtype = ptr->base + S_VTYPE; // SymTab[SymTab[c][S_VTYPE]][S_NEXT]][S_VTYPE]
            if (*vtype != _10sequence_type)
                op = 92; // RHS_SUBS_CHECK
        }
    }
    else {
        // mode != M_CONSTANT || not sequence(SymTab[c][S_OBJ])
        if (mode != 2 || !IS_SEQUENCE(Base[S_OBJ]))
            op = 92; // RHS_SUBS_CHECK
    }

    _14emit(op);
    _14emit(b);
    _14emit(a);
    _14emit(target);
    *(point0 - 1) = target;

    end = ptr0->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    Append(&_14current_sequence, _14current_sequence, target);
    _14assignable = 1; // TRUE
    _14previous_op = op;
    return op;
}

void emit_right_brace_n()
{
    int a, elements, element_vals, end, i, n, ptr_;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    n = _14op_info1;

    ptr_ = NewS1(n);
    Base = ((s1_ptr)ptr_)->base;
    i = 0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length + 1; /* Add one or we'll miss the first element. */

    while(n > i) {
        i++;
        Base[i] = *(point0 - i); /* Grab all elements from right to left. */
    }

    /* Now, snip it all at once. */
    end = ptr0->length - i;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    elements = MAKE_SEQ(ptr_);
    RefDS(elements);
    element_vals = _14good_string(elements);

    if (IS_SEQUENCE(element_vals)) {
        Ref(element_vals);
        a = _10NewStringSym(element_vals); /* make a string literal */

        _14assignable = 0; // FALSE
    }
    else {
        if (n == 2)
            _14emit(85); // RIGHT_BRACE_2 /* Faster for two items. */
        else {
            _14emit(31); // RIGHT_BRACE_N
            _14emit(n);
        }

        i = 0;
        ptr = SEQ_PTR(elements);
        Base = ptr->base;

        while (n > i) {
            i++;
            _14emit(*(Base + i));
        }

        a = _10NewTempSym();
        _14emit(a);
        _14assignable = 1; // TRUE
    }

    _14Push(a);
    _14previous_op = 31; // RIGHT_BRACE_N
}

void emit_routine_id()
{
    int a;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(136); // ROUTINE_ID

    _14emit(_4CurrentSub);
    _14emit(SEQ_PTR(_4SymTab)->length);
    _14emit(*point); /* source */
    _14emit(_4current_file_no); /* necessary at top level */

    a = _10NewTempSym();
    _14TempInteger(a); /* result will always be an integer */

    *point = a;
    _14emit(a);

    _14assignable = 1; // TRUE
}

void emit_sc1andor(int op)
{
    int a;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    _14emit(*point);
    a = _10NewTempSym();
    *point = a;
    _14emit(a);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_sc2andor(int op)
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    _14emit(op);
    _14emit(*point);
    _14emit(*(point - 1)); /* target */

    /* Only cut back 1 for this time. 2 will segfault us. */
    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = op;
}

void emit_sc2null()
{
    int end;
    object_ptr point;
    s1_ptr ptr;

    ptr = SEQ_PTR(_14cg_stack);
    point = ptr->base + ptr->length;

    *(point - 1) = *point;
    /* Override SC1 temp with last value */

    end = ptr->length - 1;
    rhs_slice_target = (object_ptr)&_14cg_stack;
    RHS_Slice((s1_ptr)_14cg_stack, 1, end);

    _14assignable = 0; // FALSE
    _14previous_op = 147; // SC2_NULL
}

void emit_sequence_check()
{
    int c;
    object_ptr Base;
    s1_ptr ptr;

    _14assignable = 0; // FALSE

    if (_14previous_op == 18) { // ASSIGN
        ptr = SEQ_PTR(_4Code);
        c = *(ptr->base + ptr->length - 1); // Code[$-1]

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + c;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // if (SymTab[c][S_MODE] != M_CONSTANT || not sequence(SymTab[c][S_OBJ])
        if (Base[S_MODE] != 2 || IS_SEQUENCE(Base[S_OBJ]) == 0) {
            _14emit(97); // SEQUENCE_CHECK
            _14emit(_14op_info1);
        }
    }
    else {
        ptr = SEQ_PTR(_14op_result);
        Base = ptr->base + _14previous_op; // op_result[previous_op]

        // previous_op == -1 || op_result[previous_op] != T_SEQUENCE
        if (_14previous_op == -1 || *Base != 3) {
            _14emit(97); // SEQUENCE_CHECK
            _14emit(_14op_info1);
        }
    }
    _14previous_op = 97; // SEQUENCE_CHECK
}

void emit_trace()
{
    int a;
    a = _14Pop();

    if (_4OpTrace) {
        _14emit(64); // TRACE
        _14emit(a);
    }

    _14assignable = 0; // FALSE
}

void emit_type_check()
{
    int a;
    _14emit(65); // TYPE_CHECK
    a = _14Pop();
    _14assignable = 0; // FALSE
    _14previous_op = 65; // TYPE_CHECK
}

void emit_uminus()
{
    int a, end, obj;
    object_ptr Base, point0;
    s1_ptr ptr, ptr0;

    ptr0 = SEQ_PTR(_14cg_stack);
    point0 = ptr0->base + ptr0->length;

    a = *point0;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + a;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    obj = ptr->base[S_OBJ]; // SymTab[a][S_OBJ]

    // if SymTab[a][S_MODE] = M_CONSTANT then
    if (Base[S_MODE] != 2 && IS_ATOM_INT(obj)) {
            if (obj == -1073741824) // MININT_VAL
                *point0 = _10NewDoubleSym(1073741824); // -MININT_VAL
            else
                *point0 = _10NewIntSym(-obj);
    }
    else {
        *point0 = a;
        _14cont11ii(12, 0);
    }
    _14previous_op = 12; // UMINUS
}

int _14emit_op(int op)
{
    int _2667;

    switch (op) {
        case 27: // PROC /* procedure, function, and type calls */
            emit_proc();
            break;
        case 59: // CLEAR_SCREEN
        case 88: // ERASE_PRIVATE_NAMES
        case 87: // DISPLAY_VAR
            emit_m1(op);
            break;
        case 62: // RAND
        case 127: // PEEK
        case 141: // PEEK4S
        case 142: // PEEK4U
        case 51: // NOT_BITS
            _14cont11ii(op, 1);
            break;
        case 175: // TASK_STATUS
        case 94: // IS_AN_INTEGER
        case 67: // IS_AN_ATOM
        case 68: // IS_A_SEQUENCE
        case 40: // IS_AN_OBJECT
        case 42: // LENGTH
        case 33: // GETC
        case 41: // SQRT
        case 80: // SIN
        case 81: // COS
        case 82: // TAN
        case 73: // ARCTAN
        case 74: // LOG
        case 17: // GETS
        case 131: // GET_PIXEL
        case 91: // GET_ENV
            _14cont11ii(op, 0);
            break;
        case 136: // ROUTINE_ID
            emit_routine_id();
            break;
        case 99: // SYSTEM
        case 44: // PUTS
        case 19: // PRINT
        case 60: // POSITION
        case 112: // MACHINE_PROC
        case 130: // PIXEL
        case 128: // POKE
        case 140: // POKE4
        case 170: // TASK_SCHEDULE
        case 138: // CALL_PROC
            emit_m2(op);
            break;
        case 135: // C_FUNC
            emit_c_func();
            break;
        case 134: // C_PROC
            emit_c_proc();
            break;
        case 35: // APPEND
        case 57: // PREPEND
        case 76: // COMPARE
        case 155: // EQUAL
        case 77: // FIND
        case 78: // MATCH
        case 156: // SYSTEM_EXEC
        case 15: // CONCAT
        case 32: // REPEAT
        case 111: // MACHINE_FUNC
        case 37: // OPEN
        case 53: // SPRINTF
        case 169: // TASK_CREATE
            _14cont21ii(op, 0);
            break;
        case 132: // MEM_COPY
        case 133: // MEM_SET
        case 38: // PRINTF
            emit_m3(op);
            break;
        case 139: // CALL_FUNC
            emit_call_func();
            break;
        case 69: // DATE
        case 70: // TIME
        case 75: // SPACE_USED
        case 174: // TASK_LIST
        case 100: // COMMAND_LINE
            emit_m4(op);
            break;
        case 71: // REMAINDER
        case 56: // AND_BITS
        case 24: // OR_BITS
        case 26: // XOR_BITS
            _14cont21ii(op, 1);
            break;
        case 79: // GET_KEY
            emit_get_key();
            break;
        case 83: // FLOOR
            op = emit_floor();
            break;
        case 72: // POWER
            op = emit_power();
            break;
        case 157: // PLATFORM
            emit_platform();
            break;
        case 86: // CLOSE
        case 126: // ABORT
        case 129: // CALL
        case 153: // PROFILE
        case 173: // TASK_SUSPEND
            emit_m5(op);
            break;
        case 64: // TRACE
            emit_trace();
            break;
        default:
            /* INTERNAL ERROR! Unknown opcode : %d */
            err_add("INTERNAL ERROR! Unknown opcode : ");
            err_add(s1_from_int(op));

            /* Since this is internal, output to screen and cleanup. */
            _6screen_output(1, error_stack);
            _6Cleanup(1);
    }

    _14previous_op = op;
}

int _14emit_assign_op(int op)
{
    switch(op) {
        case 518: // PLUS_EQUALS
            _14previous_op = emit_plus(); // PLUS
            break;
        case 519: // MINUS_EQUALS
            _14cont21ii(10, 0); // MINUS
            break;
        case 520: // MULTIPLY_EQUALS
            emit_multiply(); // MULTIPLY
            break;
        case 521: // DIVIDE_EQUALS
            _14previous_op = emit_divide(); // DIVIDE
            break;
        case 522: // CONCAT_EQUALS
            _14cont21ii(15, 0); // CONCAT
            break;
    }
}

int _14StartSourceLine(int sl)
{
    int line_span, ptr_;
    object_ptr Base;
    s1_ptr ptr;

    if (_4gline_number == _11LastLineNumber) {
        if (ptr_) {
            return 0; /* ignore duplicates */
        }
        else {
            sl = 0; // FALSE /* top-level new statement to execute on same line */
        }
    }

    _11LastLineNumber = _4gline_number;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4CurrentSub; // SymTab[CurrentSub]
    ptr = SEQ_PTR(*Base);
    Base = ptr->base + S_FIRSTLINE; // SymTab[CurrentSub][S_FIRSTLINE]

    if (sl && _4OpTrace || _4OpProfileStatement) {
        emit_m1(58); // STARTLINE
        _14emit(_4gline_number);
    }
}

